package com.jackie.easyble.ui.activities.connect.single

import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattDescriptor
import android.bluetooth.le.ScanResult
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.EditText
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager
import com.chad.library.adapter4.BaseQuickAdapter
import com.jackie.easyble.App
import com.jackie.easyble.IntentConstants
import com.jackie.easyble.R
import com.jackie.easyble.bean.BluetoothGattServiceWithBoolean
import com.jackie.easyble.databinding.ActivitySingleConnectBinding
import com.jackie.easyble.dismissConnecting
import com.jackie.easyble.dismissSending
import com.jackie.easyble.showConnecting
import com.jackie.easyble.showSending
import com.jackie.easyble.toastL
import com.jackie.easyble.ui.adapter.DeviceServiceRecyclerViewAdapter
import com.jackie.easyble.ui.dialogs.ChangeConnectedPhyDialog
import com.jackie.easyble.ui.dialogs.WriteDataDialog
import com.jackie.easyble.warnOut
import com.sscl.baselibrary.activity.BaseDataBindingAppCompatActivity
import com.sscl.baselibrary.utils.DebugUtil
import com.sscl.baselibrary.utils.DefaultItemDecoration
import com.sscl.baselibrary.utils.Tool
import com.sscl.baselibrary.utils.getByteArray
import com.sscl.baselibrary.utils.toHexStringWithSpace
import com.sscl.easyble.BleManager
import com.sscl.easyble.DeviceBoundErrorCode
import com.sscl.easyble.enums.BlePhy
import com.sscl.easyble.enums.BlePhyOptions
import com.sscl.easyble.enums.bleconnect.BleConnectPhyMask
import com.sscl.easyble.enums.bleconnect.BleConnectTransport
import com.sscl.easyble.interfaces.OnDeviceBondStateChangedListener
import com.sscl.easyble.interfaces.connections.OnBleConnectStateChangedListener
import com.sscl.easyble.interfaces.connections.OnCharacteristicDataOptionsListener
import com.sscl.easyble.interfaces.connections.OnDescriptorDataOptionListener
import com.sscl.easyble.interfaces.connections.OnLargeCharacteristicDataWriteListener
import com.sscl.easyble.interfaces.connections.OnLargeCharacteristicDataWriteWithNotificationListener
import com.sscl.easyble.interfaces.connections.OnMtuChangedListener
import com.sscl.easyble.interfaces.connections.OnPhyOptionsListener
import com.sscl.easyble.interfaces.connections.OnReadRemoteRssiListener
import com.sscl.easyble.interfaces.connections.OnReliableWriteCompletedListener
import java.util.concurrent.TimeUnit


/**
 * 单设备连接界面
 */
class SingleConnectActivity :
    BaseDataBindingAppCompatActivity<ActivitySingleConnectBinding>() {

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 静态声明
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    companion object {
        /**
         * 默认的重连参数
         */
        private const val DEFAULT_RECONNECT = false

        /**
         * 默认的GATT传输层
         */
        @RequiresApi(Build.VERSION_CODES.M)
        private val DEFAULT_BLE_CONNECT_TRANSPORT = BleConnectTransport.TRANSPORT_AUTO

        /**
         * 默认的GATT传输层名称
         */
        private val DEFAULT_BLE_CONNECT_TRANSPORT_NAME =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                App.instance.getString(R.string.transport_auto)
            } else {
                App.instance.getString(R.string.ble_connect_transport_not_support_with_low_system_version)
            }

        /**
         * 默认的GATT物理层
         */
        @RequiresApi(Build.VERSION_CODES.O)
        private val DEFAULT_BLE_CONNECT_PHY_MASK = BleConnectPhyMask.PHY_LE_1M_MASK

        /**
         * 默认的GATT物理层名称
         */
        private val DEFAULT_BLE_CONNECT_PHY_MASK_NAME =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                App.instance.getString(R.string.connect_phy_le_1m_mask)
            } else {
                App.instance.getString(R.string.ble_connect_phy_mask_not_support_with_low_system_version)
            }
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 属性声明
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /* * * * * * * * * * * * * * * * * * * 可空属性 * * * * * * * * * * * * * * * * * * */

    /**
     * 某个设备
     */
    private var scanResult: ScanResult? = null

    /* * * * * * * * * * * * * * * * * * * 可变属性 * * * * * * * * * * * * * * * * * * */

    /**
     * 设备是否已连接
     */
    private var connected = false

    /**
     * 记录当前是否已经开启可靠传输事务
     */
    private var reliableWriteBegin = false

    /**
     * 最大单包数据
     */
    private var singlePackMaxCount = 0

    /* * * * * * * * * * * * * * * * * * * 常量属性 * * * * * * * * * * * * * * * * * * */

    /**
     * viewModel
     */
    private val singleConnectActivityViewModel by viewModels<SingleConnectActivityViewModel> {
        SingleConnectActivityViewModel.SingleConnectActivityViewModelFactory
    }

    /**
     * 设备服务列表适配器
     */
    private val deviceServiceRecyclerViewAdapter = DeviceServiceRecyclerViewAdapter()

    /**
     * 设备服务列表-特征操作处理
     */
    private val onCharacterOptionClickListener =
        object : DeviceServiceRecyclerViewAdapter.OnCharacterOptionClickListener {
            override fun onCharacterOption(characteristic: BluetoothGattCharacteristic) {
                warnOut(
                    "characteristic = ${characteristic.uuid}"
                )
                showCharacteristicOptionsDialog(characteristic)
            }

        }

    /**
     * 设备服务列表-描述操作处理
     */
    private val onDescriptorOptionClickListener =
        object : DeviceServiceRecyclerViewAdapter.OnDescriptorOptionClickListener {
            override fun onDescriptorOption(descriptor: BluetoothGattDescriptor) {
                warnOut(
                    "descriptorUuid = ${descriptor.uuid}"
                )
                showDescriptorOptionsDialog(descriptor)
            }
        }

    /**
     *  设备服务列表-服务操作处理
     */
    private val onItemLongClickListener =
        BaseQuickAdapter.OnItemLongClickListener<BluetoothGattServiceWithBoolean> { adapter, view, position ->
            val bluetoothGattServiceWithBoolean = adapter.getItem(position)
            val bluetoothGattService = bluetoothGattServiceWithBoolean?.bluetoothGattService
                ?: return@OnItemLongClickListener true
            warnOut(
                "serviceUUID = ${bluetoothGattService.uuid}"
            )
            Tool.setDataToClipboard(
                this@SingleConnectActivity,
                "uuidString",
                bluetoothGattService.uuid.toString()
            )
            toastL(R.string.service_uuid_copied)
            return@OnItemLongClickListener true
        }

    /**
     * 点击事件
     */
    private val onClickListener = View.OnClickListener {
        when (it.id) {
            binding.button.id -> {
                doButtonClicked()
            }
        }
    }

    /**
     * 设备绑定（配对）状态变化回调
     */
    private val onDeviceBondStateChangedListener = object : OnDeviceBondStateChangedListener {
        /**
         * 设备正在绑定
         */
        override fun onDeviceBinding() {
            DebugUtil.warnOut(TAG, "onDeviceBinding")
        }

        /**
         * 设备已经绑定
         */
        override fun onDeviceBonded() {
            DebugUtil.warnOut(TAG, "onDeviceBonded")
            connectDevice()
        }

        /**
         * 绑定被取消或绑定失败
         */
        override fun onDeviceBindNone() {
            DebugUtil.warnOut(TAG, "onDeviceBindNone")
        }

        /**
         * 未知的的绑定状态
         */
        override fun unknownBoundState(bondState: Int) {
            DebugUtil.warnOut(TAG, "unknownBoundState $bondState")
        }

    }

    /**
     *  蓝牙连接状态变化监听器
     */
    private val onBleConnectStateChangedListener = object : OnBleConnectStateChangedListener {
        /**
         * 设备已连接
         *
         * @param gattState GATT操作状态
         * [android.bluetooth.BluetoothGatt.GATT_SUCCESS]表示成功
         */
        override fun onConnected(address: String, gattState: Int) {
            binding.circlePointView.setColor(Color.BLUE)
        }

        /**
         * 设备已断开连接
         *
         * @param gattState GATT操作状态
         * [android.bluetooth.BluetoothGatt.GATT_SUCCESS]表示成功
         */
        override fun onDisconnected(address: String, gattState: Int) {
            connected = false
            binding.circlePointView.setColor(Color.RED)
            singleConnectActivityViewModel.buttonText.value = getString(R.string.connect_device)
            refreshAdapterData()
        }

        /**
         * 连接超时
         */
        override fun connectTimeout(address: String) {
            dismissConnecting()
            connected = false
            BleManager.getConnectorInstance().closeGatt(address)
            binding.circlePointView.setColor(Color.MAGENTA)
            toastL(R.string.connect_timeout)
        }

        /**
         * 设备正在连接
         *
         *  @param gattState GATT操作状态
         *  [android.bluetooth.BluetoothGatt.GATT_SUCCESS]表示成功
         */
        override fun onConnecting(address: String, gattState: Int) {
            warnOut("onConnecting")
        }

        /**
         * 设备正在断开连接
         *
         *  @param gattState GATT操作状态
         *  [android.bluetooth.BluetoothGatt.GATT_SUCCESS]表示成功
         */
        override fun onDisconnecting(address: String, gattState: Int) {
            warnOut("onDisconnecting")
        }

        /**
         * 未知的设备状态
         *
         * @param gattState GATT操作状态
         * [android.bluetooth.BluetoothGatt.GATT_SUCCESS]表示成功
         */
        override fun onUnknownStatus(address: String, gattState: Int, newState: Int) {
            warnOut("GATT连接状态未知")
            dismissConnecting()
            BleManager.getConnectorInstance().closeGatt(address)
            binding.circlePointView.setColor(Color.MAGENTA)
            toastL(getString(R.string.connect_state_err, gattState))
            connected = false
        }

        /**
         *  发现设备的服务
         *  @param gattState GATT操作状态
         * [android.bluetooth.BluetoothGatt.GATT_SUCCESS]表示成功
         */
        override fun onServicesDiscovered(address: String, gattState: Int) {
            connected = true
            binding.circlePointView.setColor(Color.GREEN)
            singleConnectActivityViewModel.buttonText.value = getString(R.string.disconnect_device)
            dismissConnecting()
            refreshAdapterData()
            toastL(R.string.connected)
            BleManager.getConnectorInstance().requestMtu(address, 512)
        }

        /**
         * 发现服务失败
         */
        override fun onDiscoverServicesFailed(address: String) {
            dismissConnecting()
            connected = false
            binding.circlePointView.setColor(Color.MAGENTA)
            BleManager.getConnectorInstance().closeGatt(address)
            toastL(R.string.discover_services_failed)
        }
    }

    /**
     * 蓝牙 操作描述的相关回调
     */
    private val onDescriptorDataOptionListener = object : OnDescriptorDataOptionListener {
        /**
         * 读取到描述数据
         */
        override fun onDescriptorRead(
            address: String,
            descriptor: BluetoothGattDescriptor,
            value: ByteArray,
            gattState: Int
        ) {
            if (gattState != BluetoothGatt.GATT_SUCCESS) {
                toastL(
                    String.format(
                        "读取描述数据 GATT错误，状态码：%d 0x(%02X)",
                        gattState,
                        gattState
                    )
                )
                return
            }
            showReadDataResultDialog(descriptor.uuid.toString(), value)
        }

        /**
         * 写入描述数据操作结果
         * @param gattState [android.bluetooth.BluetoothGatt.GATT_SUCCESS]表示操作成功
         */
        override fun onDescriptorWrite(
            address: String,
            descriptor: BluetoothGattDescriptor,
            gattState: Int
        ) {
            if (gattState != BluetoothGatt.GATT_SUCCESS) {
                toastL(
                    String.format(
                        "写入描述数据 GATT错误，状态码：%d 0x(%02X)",
                        gattState,
                        gattState
                    )
                )
                return
            }
            @Suppress("DEPRECATION")
            showWriteDataResultDialog(descriptor.uuid.toString(), descriptor.value, false)
        }
    }

    /**
     * 蓝牙 操作特征的相关回调
     */
    private val onCharacteristicDataOptionsListener = object : OnCharacteristicDataOptionsListener {
        /**
         * 读取到特征数据
         */
        override fun onCharacteristicRead(
            address: String,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray,
            gattState: Int
        ) {
            showReadDataResultDialog(characteristic.uuid.toString(), value)
        }

        /**
         * 写入特征数据操作结果
         * @param gattState [android.bluetooth.BluetoothGatt.GATT_SUCCESS]表示操作成功
         */
        override fun onCharacteristicWrite(
            address: String,
            characteristic: BluetoothGattCharacteristic,
            gattState: Int
        ) {
            DebugUtil.warnOut(TAG, "onCharacteristicWrite ")
            @Suppress("DEPRECATION")
            showWriteDataResultDialog(characteristic.uuid.toString(), characteristic.value, true)
        }

        /**
         * 特征数据通知
         */
        override fun onCharacteristicNotify(
            address: String,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray
        ) {
            showNotifyDataDialog(characteristic, value)
        }

    }

    /**
     * 读取远程设备的 RSSI 值
     */
    private val onReadRemoteRssiListener = OnReadRemoteRssiListener { _, rssi, gattState ->
        if (gattState != BluetoothGatt.GATT_SUCCESS) {
            toastL(
                String.format(
                    "读取远程设备RSSI GATT错误，状态码：%d 0x(%02X)",
                    gattState,
                    gattState
                )
            )
            return@OnReadRemoteRssiListener
        }
        toastL(rssi.toString())
    }

    /**
     * 读取远程设备的 RSSI 值
     */
    private val onMtuChangedListener = OnMtuChangedListener { _, mtu, gattState ->
        if (gattState != BluetoothGatt.GATT_SUCCESS) {
            toastL(
                String.format(
                    "设备MTU变化 GATT错误，状态码：%d 0x(%02X)",
                    gattState,
                    gattState
                )
            )
            return@OnMtuChangedListener
        }
        singlePackMaxCount = mtu - 1
        toastL(getString(R.string.mtu_changed, mtu))
    }

    /**
     * PHY操作回调
     */
    @RequiresApi(Build.VERSION_CODES.O)
    private val onPhyOptionsListener = object : OnPhyOptionsListener {
        /**
         * @param address 设备地址
         */
        override fun onPhyUpdate(address: String, txPhy: BlePhy, rxPhy: BlePhy, gattState: Int) {
            if (gattState != BluetoothGatt.GATT_SUCCESS) {
                toastL(
                    String.format(
                        "PHY更新 GATT错误，状态码：%d 0x(%02X)",
                        gattState,
                        gattState
                    )
                )
                return
            }
            showPhyUpdateDialog(txPhy, rxPhy)
        }

        override fun onPhyRead(address: String, txPhy: BlePhy, rxPhy: BlePhy, gattState: Int) {
            if (gattState != BluetoothGatt.GATT_SUCCESS) {
                toastL(
                    String.format(
                        "PHY读取 GATT错误，状态码：%d 0x(%02X)",
                        gattState,
                        gattState
                    )
                )
                return
            }
            showPhyReadResultDialog(txPhy, rxPhy)
        }

    }

    private val onReliableWriteCompletedListener =
        OnReliableWriteCompletedListener { address, gattState ->
            if (gattState != BluetoothGatt.GATT_SUCCESS) {
                toastL(
                    String.format(
                        "PHY读取 GATT错误，状态码：%d 0x(%02X)",
                        gattState,
                        gattState
                    )
                )
                return@OnReliableWriteCompletedListener
            }
            toastL("可靠数据写入成功")
        }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 实现方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /**
     * 设置布局
     */
    override fun setLayout(): Int {
        return R.layout.activity_single_connect
    }

    /**
     * 标题栏的返回按钮被按下的时候回调此方法
     */
    override fun titleBackClicked(): Boolean {
        return false
    }

    /**
     * 在设置布局之前需要进行的操作
     */
    override fun doBeforeSetLayout() {
        getIntentData()
    }

    /**
     * 设置DataBinding
     * 可在此处设置binding的viewModel或观察者等操作
     */
    override fun setBinding() {
        binding.viewModel = singleConnectActivityViewModel
        initViewModelData()
    }

    /**
     * 在设置布局之后，进行其他操作之前，所需要初始化的数据
     */
    override fun doBeforeInitOthers() {
        setTitleText(R.string.connect_device)
    }

    /**
     * 初始化控件数据
     */
    override fun initViewData(savedInstanceState: Bundle?) {
        binding.servicesCharacteristicsListRv.layoutManager = LinearLayoutManager(this)
        binding.servicesCharacteristicsListRv.addItemDecoration(DefaultItemDecoration.newLine(Color.GRAY))
        binding.servicesCharacteristicsListRv.adapter = deviceServiceRecyclerViewAdapter
    }

    /**
     * 初始化其他数据
     */
    override fun initOtherData() {

    }

    /**
     * 初始化事件
     */
    override fun initEvents() {
        binding.button.setOnClickListener(onClickListener)
        deviceServiceRecyclerViewAdapter.setOnItemLongClickListener(onItemLongClickListener)
        deviceServiceRecyclerViewAdapter.setOnDescriptorOptionClickListener(
            onDescriptorOptionClickListener
        )
        deviceServiceRecyclerViewAdapter.setOnCharacterOptionClickListener(
            onCharacterOptionClickListener
        )
        BleManager.addDeviceBoundStateChangedListener(
            scanResult?.device ?: return,
            onDeviceBondStateChangedListener
        )
        initBleConnector()
    }

    /**
     * 在最后进行的操作
     */
    override fun doAfterAll() {
        if (scanResult == null) {
            finish()
            return
        }
        setData()
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 重写方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.activity_single_connect, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.auto_reconnect -> {
                showSetAutoReconnectDialog()
            }

            R.id.ble_connect_transport -> {
                showSetBleConnectTransportDialog()
            }

            R.id.ble_connect_phy_mask -> {
                showSetBleConnectPhyMaskDialog()
            }

            R.id.ble_connect_timeout -> {
                showSetConnectTimeoutDialog()
            }

            R.id.ble_additional_options -> {
                showAdditionalOptionsDialog()
            }

            R.id.bind_device -> {
                bindDevice()
            }

            else -> {
                return false
            }
        }
        return true
    }

    override fun onDestroy() {
        super.onDestroy()
        BleManager.releaseConnectorInstance()
        BleManager.removeDeviceBoundStateChangedListener(scanResult?.device ?: return)
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 私有方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /**
     * 获取Intent传递的数据
     */
    private fun getIntentData() {
        scanResult = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            intent.getParcelableExtra(IntentConstants.SCAN_RESULT, ScanResult::class.java)
        } else {
            @Suppress("DEPRECATION")
            intent.getParcelableExtra(IntentConstants.SCAN_RESULT)
        }
    }

    /**
     * 设置基本数据
     */
    private fun setData() {
        singleConnectActivityViewModel.scanResult.value = scanResult
        singleConnectActivityViewModel.buttonText.value = getString(R.string.connect_device)
    }

    private fun initBleConnector() {
        val device = scanResult?.device ?: return

        val connector = BleManager.getConnectorInstance()
            .setOnDescriptorDataOptionListener(device, onDescriptorDataOptionListener)
            .setOnCharacteristicDataOptionsListener(device, onCharacteristicDataOptionsListener)
            .setonReadRemoteRssiListener(device, onReadRemoteRssiListener)
            .setOnMtuChangedListener(device, onMtuChangedListener)
            .setOnReliableWriteCompletedListener(device, onReliableWriteCompletedListener)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            connector.setOnPhyOptionsListener(device, onPhyOptionsListener)
        }
    }

    /**
     * 初始化ViewModel数据
     */
    private fun initViewModelData() {
        singleConnectActivityViewModel.autoReconnect.value = DEFAULT_RECONNECT
        singleConnectActivityViewModel.bleConnectTransportName.value =
            DEFAULT_BLE_CONNECT_TRANSPORT_NAME
        singleConnectActivityViewModel.bleConnectPhyMaskName.value =
            DEFAULT_BLE_CONNECT_PHY_MASK_NAME
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            singleConnectActivityViewModel.bleConnectTransport.value = DEFAULT_BLE_CONNECT_TRANSPORT
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            singleConnectActivityViewModel.bleConnectPhyMask.value = DEFAULT_BLE_CONNECT_PHY_MASK
        }
    }

    /**
     * 按钮点击的处理
     */
    @Synchronized
    private fun doButtonClicked() {
        val scanResult = scanResult ?: return
        if (connected) {
            val succeed = BleManager.getConnectorInstance().disconnect(scanResult.device)
            warnOut("断开设备：succeed $succeed")
        } else {
            connectDevice()
        }
    }

    /**
     * 连接设备
     */
    private fun connectDevice() {
        val scanResult = scanResult ?: return
        val succeed = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            BleManager.getConnectorInstance().connectDevice(
                scanResult.device,
                onBleConnectStateChangedListener,
                singleConnectActivityViewModel.autoReconnect.value ?: DEFAULT_RECONNECT,
                singleConnectActivityViewModel.bleConnectTransport.value
                    ?: DEFAULT_BLE_CONNECT_TRANSPORT,
                singleConnectActivityViewModel.bleConnectPhyMask.value
                    ?: DEFAULT_BLE_CONNECT_PHY_MASK
            )
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            BleManager.getConnectorInstance().connectDevice(
                scanResult.device,
                onBleConnectStateChangedListener,
                singleConnectActivityViewModel.autoReconnect.value ?: DEFAULT_RECONNECT,
                singleConnectActivityViewModel.bleConnectTransport.value
                    ?: DEFAULT_BLE_CONNECT_TRANSPORT
            )
        } else {
            BleManager.getConnectorInstance().connectDevice(
                scanResult.device,
                onBleConnectStateChangedListener,
                singleConnectActivityViewModel.autoReconnect.value ?: DEFAULT_RECONNECT
            )
        }
        if (succeed) {
            showConnecting()
            binding.circlePointView.setColor(Color.YELLOW)
        }
    }

    /**
     * 更新并展示服务信息
     */
    private fun refreshAdapterData() {
        val device = scanResult?.device ?: return
        while (true) {
            if (deviceServiceRecyclerViewAdapter.items.isEmpty()) {
                break
            }
            deviceServiceRecyclerViewAdapter.removeAt(0)
        }
        if (!connected) {
            return
        }
        val services = BleManager.getConnectorInstance().getServices(device) ?: return

        for (service in services) {
            deviceServiceRecyclerViewAdapter.add(BluetoothGattServiceWithBoolean(false, service))
        }
    }

    /**
     * 显示描述
     */
    private fun showDescriptorOptionsDialog(descriptor: BluetoothGattDescriptor) {
        val device = scanResult?.device ?: return
        AlertDialog.Builder(this)
            .setTitle(R.string.please_select_operate_dialog_title)
            .setItems(R.array.descriptor_options) { _, which ->
                when (which) {
                    //读数据
                    0 -> {
//                        if (!BleManager.descriptorCanRead(descriptor)) {
//                            toastL(R.string.descriptor_can_not_read)
//                            return@setItems
//                        }
                        val succeed = BleManager.getConnectorInstance().readDescriptorData(
                            device,
                            descriptor
                        )
                        if (!succeed) {
                            toastL(R.string.descriptor_read_failed)
                        }
                    }
                    //写数据
                    1 -> {
//                        if (!BleManager.descriptorCanWrite(descriptor)) {
//                            toastL(R.string.descriptor_can_not_write)
//                            return@setItems
//                        }
                        showWriteDescriptorDataDialog(descriptor)
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示写入描述数据的对话框
     */
    private fun showWriteDescriptorDataDialog(descriptor: BluetoothGattDescriptor) {
        val device = scanResult?.device ?: return
        WriteDataDialog(this, object : WriteDataDialog.OnConfirmButtonClickedListener {
            /**
             * 字符串数据
             */
            /**
             * 字符串数据
             */
            override fun stringData(string: String) {
                val byteArray = string.getByteArray(20)
                if (byteArray == null) {
                    warnOut("字符串数据：$string 格式错误")
                    return
                }
                val succeed = BleManager.getConnectorInstance().writeCompatDescriptorData(
                    device,
                    descriptor,
                    byteArray
                )
                if (!succeed) {
                    toastL(R.string.descriptor_write_failed)
                }
            }

            /**
             * 十六进制数据
             */
            /**
             * 十六进制数据
             */
            override fun hexData(byteArray: ByteArray) {
                warnOut("写入十六进制数据：${byteArray.toHexStringWithSpace()}")
                val succeed = BleManager.getConnectorInstance().writeCompatDescriptorData(
                    device,
                    descriptor,
                    byteArray
                )
                if (!succeed) {
                    toastL(R.string.descriptor_write_failed)
                }
            }

        }).show()
    }

    /**
     * 显示特征的操作方式的对话框
     *
     * @param characteristic 特征UUID
     */
    private fun showCharacteristicOptionsDialog(
        characteristic: BluetoothGattCharacteristic
    ) {
        val device = scanResult?.device ?: return
        AlertDialog.Builder(this)
            .setTitle(R.string.please_select_operate_dialog_title)
            .setItems(R.array.characteristic_options) { _, which ->
                when (which) {
                    //读数据
                    0 -> {
                        if (!BleManager.characteristicCanRead(characteristic)) {
                            toastL(R.string.characteristic_can_not_read)
                            return@setItems
                        }
                        if (!BleManager.getConnectorInstance().readCharacteristicData(
                                device,
                                characteristic
                            )
                        ) {
                            toastL(R.string.characteristic_read_failed)
                            return@setItems
                        }
                    }
                    //写数据
                    1 -> {
                        if (!BleManager.characteristicCanWrite(characteristic)) {
                            toastL(R.string.characteristic_can_not_write)
                            return@setItems
                        }
                        showWriteCharacteristicDataDialog(characteristic)
                    }
                    //开启通知
                    2 -> {
                        if (!BleManager.characteristicCanNotify(characteristic)) {
                            toastL(R.string.characteristic_can_not_notify)
                            return@setItems
                        }
                        if (!BleManager.getConnectorInstance().enableNotification(
                                device,
                                characteristic,
                                true
                            )
                        ) {
                            toastL(R.string.characteristic_notify_enable_failed)
                        } else {
                            toastL(R.string.characteristic_notify_enable_succeed)
                        }
                    }
                    //复制UUID
                    3 -> {
                        Tool.setDataToClipboard(
                            this@SingleConnectActivity,
                            "uuidString",
                            characteristic.uuid.toString()
                        )
                        toastL(R.string.characteristic_uuid_copied)
                    }
                    //写入数据-无长度限制
                    4 -> {
                        if (!BleManager.characteristicCanWrite(characteristic)) {
                            toastL(R.string.characteristic_can_not_write)
                            return@setItems
                        }
                        showWriteLargeCharacteristicDataDialog(characteristic)
                    }

                    5 -> {
                        if (!BleManager.characteristicCanWrite(characteristic)) {
                            toastL(R.string.characteristic_can_not_write)
                            return@setItems
                        }
                        showWriteLargeCharacteristicDataWithNotificationDialog(characteristic)
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    private fun showWriteLargeCharacteristicDataWithNotificationDialog(characteristic: BluetoothGattCharacteristic) {
        val device = scanResult?.device ?: return
        val callback = object : OnLargeCharacteristicDataWriteWithNotificationListener {
            /**
             * 启动失败
             */
            override fun startFailed() {
                DebugUtil.warnOut(TAG, "写入失败")
                dismissSending()
            }

            /**
             * 开始发送数据
             */
            override fun sendStarted() {
                DebugUtil.warnOut(TAG, "开始发送数据")
                showSending()
            }

            /**
             * 发送数据异常
             */
            override fun writeDataError(
                currentIndex: Int,
                targetIndex: Int,
                gattState: Int,
                data: ByteArray
            ) {
                DebugUtil.warnOut(
                    TAG,
                    "发送数据异常 currentIndex:$currentIndex, targetIndex:$targetIndex, gattState:$gattState, data:${data.toHexStringWithSpace()}"
                )
                dismissSending()
                toastL("发送数据异常 gattState$gattState")
            }

            /**
             * 发送数据失败
             */
            override fun sendFailed(
                currentIndex: Int,
                targetIndex: Int,
                data: ByteArray
            ) {
                DebugUtil.warnOut(
                    TAG,
                    "发送数据失败 currentIndex:$currentIndex, targetIndex:$targetIndex, data:${data.toHexStringWithSpace()}"
                )
                dismissSending()
                toastL("发送数据失败")
            }

            /**
             * 发送进度变化
             */
            override fun sendProgressChanged(
                currentIndex: Int,
                targetIndex: Int,
                bytes: ByteArray
            ) {
                DebugUtil.warnOut(
                    TAG,
                    "发送进度变化 currentIndex:$currentIndex, targetIndex:$targetIndex, bytes:${bytes.toHexStringWithSpace()}"
                )
            }

            /**
             * 通知返回的数据
             *
             * @return true 表示收到的通知符合校验,继续发送数据
             *         false 表示收到的通知不符合校验,停止发送数据
             */
            override fun verifyNotificationData(
                currentIndex: Int,
                targetIndex: Int,
                currentSendData: ByteArray,
                characteristic: BluetoothGattCharacteristic,
                notificationData: ByteArray
            ): Boolean {
                DebugUtil.warnOut(TAG, "验证通知数据 ${notificationData.toHexStringWithSpace()}")
                return true
            }

            /**
             * 等待通知数据超时
             * @return true  表示强制继续发送数据
             *         false 表示停止发送数据
             */
            override fun waitNotifyTimeout(
                currentIndex: Int,
                targetIndex: Int,
                currentSendData: ByteArray
            ): Boolean {
                DebugUtil.warnOut(TAG, "等待通知数据超时")
                return true
            }

            /**
             * 发送中断，有一下可能性
             * 1. 通知校验失败
             * 2. 通知接收超时，并且返回false
             */
            override fun sendIntercept(currentIndex: Int, targetIndex: Int, bytes: ByteArray) {
                dismissSending()
                DebugUtil.warnOut(TAG, "发送中断")
            }

            /**
             * 发送完成
             */
            override fun sendFinish() {
                DebugUtil.warnOut(TAG, "发送完成")
                dismissSending()
            }
        }
        WriteDataDialog(this, object : WriteDataDialog.OnConfirmButtonClickedListener {
            /**
             * 字符串数据
             */
            override fun stringData(string: String) {
                val byteArray = string.getByteArray()
                if (byteArray == null) {
                    warnOut("字符串数据：$string 格式错误")
                    return
                }
                if (singlePackMaxCount > 0) {
                    //使用MTU最大值进行分包传输
                    BleManager.getConnectorInstance().writeLargeCharacteristicDataWithNotification(
                        device,
                        characteristic,
                        byteArray,
                        callback, singlePackMaxCount
                    )
                } else {
                    BleManager.getConnectorInstance().writeLargeCharacteristicDataWithNotification(
                        device,
                        characteristic,
                        byteArray,
                        callback
                    )
                }
            }

            /**
             * 十六进制数据
             */
            override fun hexData(byteArray: ByteArray) {
                warnOut("写入十六进制数据：${byteArray.toHexStringWithSpace()}")
                if (singlePackMaxCount > 0) {
                    //使用MTU最大值进行分包传输
                    BleManager.getConnectorInstance().writeLargeCharacteristicDataWithNotification(
                        device,
                        characteristic,
                        byteArray,
                        callback,
                        singlePackMaxCount
                    )
                } else {
                    BleManager.getConnectorInstance().writeLargeCharacteristicDataWithNotification(
                        device,
                        characteristic,
                        byteArray,
                        callback
                    )
                }
            }
        }, 512).show()
    }

    private fun showWriteLargeCharacteristicDataDialog(characteristic: BluetoothGattCharacteristic) {
        val device = scanResult?.device ?: return
        val callback = object : OnLargeCharacteristicDataWriteListener {
            /**
             * 启动失败
             */
            override fun startFailed() {
                DebugUtil.warnOut(TAG, "写入失败")
                dismissSending()
            }

            /**
             * 开始发送数据
             */
            override fun sendStarted() {
                DebugUtil.warnOut(TAG, "开始发送数据")
                showSending()
            }

            /**
             * 发送数据异常
             */
            override fun writeDataError(
                currentIndex: Int,
                targetIndex: Int,
                gattState: Int,
                data: ByteArray
            ) {
                DebugUtil.warnOut(
                    TAG,
                    "发送数据异常 currentIndex:$currentIndex, targetIndex:$targetIndex, gattState:$gattState, data:${data.toHexStringWithSpace()}"
                )
                dismissSending()
                toastL("发送数据异常 gattState$gattState")
            }

            /**
             * 发送数据失败
             */
            override fun sendFailed(
                currentIndex: Int,
                targetIndex: Int,
                data: ByteArray
            ) {
                DebugUtil.warnOut(
                    TAG,
                    "发送数据失败 currentIndex:$currentIndex, targetIndex:$targetIndex, data:${data.toHexStringWithSpace()}"
                )
                dismissSending()
                toastL("发送数据失败")
            }

            /**
             * 发送进度变化
             */
            override fun sendProgressChanged(
                currentIndex: Int,
                targetIndex: Int,
                bytes: ByteArray
            ) {
                DebugUtil.warnOut(
                    TAG,
                    "发送进度变化 currentIndex:$currentIndex, targetIndex:$targetIndex, bytes:${bytes.toHexStringWithSpace()}"
                )
            }

            /**
             * 发送完成
             */
            override fun sendFinish() {
                DebugUtil.warnOut(TAG, "发送完成")
                dismissSending()
            }
        }
        WriteDataDialog(this, object : WriteDataDialog.OnConfirmButtonClickedListener {
            /**
             * 字符串数据
             */
            override fun stringData(string: String) {
                val byteArray = string.getByteArray()
                if (byteArray == null) {
                    warnOut("字符串数据：$string 格式错误")
                    return
                }
                if (singlePackMaxCount > 0) {
                    //使用MTU最大值进行分包传输
                    BleManager.getConnectorInstance().writeLargeCharacteristicData(
                        device,
                        characteristic,
                        byteArray,
                        callback, singlePackMaxCount
                    )
                } else {
                    BleManager.getConnectorInstance().writeLargeCharacteristicData(
                        device,
                        characteristic,
                        byteArray,
                        callback
                    )
                }
            }

            /**
             * 十六进制数据
             */
            override fun hexData(byteArray: ByteArray) {
                warnOut("写入十六进制数据：${byteArray.toHexStringWithSpace()}")
                if (singlePackMaxCount > 0) {
                    //使用MTU最大值进行分包传输
                    BleManager.getConnectorInstance().writeLargeCharacteristicData(
                        device,
                        characteristic,
                        byteArray,
                        callback,
                        singlePackMaxCount
                    )
                } else {
                    BleManager.getConnectorInstance().writeLargeCharacteristicData(
                        device,
                        characteristic,
                        byteArray,
                        callback
                    )
                }
            }
        }, 512).show()
    }

    private fun showWriteCharacteristicDataDialog(characteristic: BluetoothGattCharacteristic) {
        val device = scanResult?.device ?: return
        WriteDataDialog(this, object : WriteDataDialog.OnConfirmButtonClickedListener {
            /**
             * 字符串数据
             */
            override fun stringData(string: String) {
                val byteArray = string.getByteArray(20)
                if (byteArray == null) {
                    warnOut("字符串数据：$string 格式错误")
                    return
                }
                val succeed = BleManager.getConnectorInstance().writeCompatCharacteristicData(
                    device,
                    characteristic,
                    byteArray
                )
                if (!succeed) {
                    toastL(R.string.characteristic_write_failed)
                }
            }

            /**
             * 十六进制数据
             */
            override fun hexData(byteArray: ByteArray) {
                warnOut("写入十六进制数据：${byteArray.toHexStringWithSpace()}")
                val succeed = BleManager.getConnectorInstance().writeCompatCharacteristicData(
                    device,
                    characteristic,
                    byteArray
                )
                if (!succeed) {
                    toastL(R.string.characteristic_write_failed)
                }
            }

        }).show()
    }

    /**
     * 展示读取到的数据的对话框
     */
    private fun showReadDataResultDialog(
        uuidString: String,
        value: ByteArray
    ) {
        val stringValue = String(value)
        val hexValue = value.toHexStringWithSpace() ?: ""
        AlertDialog.Builder(this)
            .setTitle(R.string.read_data_result_dialog_title)
            .setMessage(
                "数据来源：$uuidString\n十六进制：$hexValue\n字符串：$stringValue"
            )
            .setPositiveButton(R.string.copy_string_content) { _, _ ->
                Tool.setDataToClipboard(this@SingleConnectActivity, TAG, stringValue)
                toastL(R.string.string_copied)
            }
            .setNegativeButton(R.string.copy_hex_content) { _, _ ->
                Tool.setDataToClipboard(this@SingleConnectActivity, TAG, hexValue)
                toastL(R.string.hex_copied)
            }
            .setNeutralButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示写入数据结果回调的对话框
     */
    private fun showWriteDataResultDialog(
        uuidString: String,
        value: ByteArray?,
        fromCharacter: Boolean = true
    ) {
        if (fromCharacter && reliableWriteBegin) {
            showReliableWriteDataResultDialog(uuidString, value)
            return
        }
        val getValue: Boolean
        val stringValue = if (value != null) {
            getValue = true
            String(value)
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                getValue = false
                "not allow to getValue with write data response"
            } else {
                getValue = true
                "null"
            }
        }
        val hexValue =
            value.toHexStringWithSpace() ?: "not allow to getValue with write data response"
        val message =
            SpannableStringBuilder("数据来源：$uuidString\n十六进制：$hexValue\n字符串：$stringValue")
        if (!getValue) {
            val colorSpan =
                ForegroundColorSpan(Color.RED)
            message.setSpan(colorSpan, 0, message.length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
        }
        AlertDialog.Builder(this)
            .setTitle(R.string.write_data_succeed_dialog_title)
            .setMessage(message)
            .setPositiveButton(R.string.confirm, null)
            .show()
    }

    /**
     * 可靠数据写入结果回调对话框
     */
    private fun showReliableWriteDataResultDialog(uuidString: String, value: ByteArray?) {
        val device = scanResult?.device ?: return
        val stringValue = if (value != null) {
            String(value)
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                "not allow to getValue with write data response"
            } else {
                "null"
            }
        }
        val hexValue =
            value.toHexStringWithSpace() ?: "not allow to getValue with write data response"
        AlertDialog.Builder(this)
            .setTitle(R.string.reliable_write_data_result_dialog_title)
            .setMessage("数据来源：$uuidString\n十六进制：$hexValue\n字符串：$stringValue")
            .setPositiveButton(R.string.commit) { _, _ ->
                val succeed = BleManager.getConnectorInstance().executeReliableWrite(device)
                if (!succeed) {
                    toastL(R.string.reliable_data_write_failed)
                    BleManager.getConnectorInstance().abortReliableWrite(device)
                    reliableWriteBegin = false
                }
            }
            .setNegativeButton(R.string.cancel_write) { _, _ ->
                abortReliableWrite()
            }
            .setNeutralButton(R.string.continue_write, null)
            .setCancelable(false)
            .show()
    }

    /**
     * 取消可靠数据写入
     */
    private fun abortReliableWrite() {
        val device = scanResult?.device ?: return
        if (!reliableWriteBegin) {
            toastL(R.string.not_in_reliable_write_mode)
            return
        }
        val succeed = BleManager.getConnectorInstance().abortReliableWrite(device)
        if (!succeed) {
            toastL(R.string.reliable_data_cancel_write_failed)
            return
        }
        reliableWriteBegin = false
        toastL(R.string.canceled)
    }

    /**
     * 显示通知数据信息的对话框
     */
    private fun showNotifyDataDialog(
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray
    ) {
        val stringValue = String(value)
        val hexValue = value.toHexStringWithSpace() ?: ""
        AlertDialog.Builder(this)
            .setTitle(R.string.notify_data_dialog_title)
            .setMessage(
                "数据来源：${characteristic.uuid}\n十六进制：$hexValue\n字符串：$stringValue"
            )
            .setPositiveButton(R.string.confirm, null)
            .show()
    }

    /**
     * 显示设置连接参数的对话框
     */
    private fun showSetAutoReconnectDialog() {
        AlertDialog.Builder(this)
            .setTitle(R.string.auto_reconnect_dialog_title)
            .setItems(R.array.booleans) { _, which ->
                when (which) {
                    //是
                    0 -> {
                        singleConnectActivityViewModel.autoReconnect.value = true
                    }
                    //否
                    1 -> {
                        singleConnectActivityViewModel.autoReconnect.value = false
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示设置GATT传输层的对话框
     */
    private fun showSetBleConnectTransportDialog() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            toastL(R.string.ble_connect_transport_not_support_with_low_system_version)
            return
        }
        AlertDialog.Builder(this)
            .setTitle(R.string.ble_reconnect_transport_dialog_title)
            .setItems(R.array.ble_reconnect_transport) { _, which ->
                when (which) {
                    //transport_auto
                    0 -> {
                        singleConnectActivityViewModel.bleConnectTransport.value =
                            BleConnectTransport.TRANSPORT_AUTO
                        singleConnectActivityViewModel.bleConnectTransportName.value =
                            getString(R.string.transport_auto)
                    }
                    //transport_br_edr
                    1 -> {
                        singleConnectActivityViewModel.bleConnectTransport.value =
                            BleConnectTransport.TRANSPORT_BR_EDR
                        singleConnectActivityViewModel.bleConnectTransportName.value =
                            getString(R.string.transport_br_edr)
                    }
                    //transport_le
                    2 -> {
                        singleConnectActivityViewModel.bleConnectTransport.value =
                            BleConnectTransport.TRANSPORT_LE
                        singleConnectActivityViewModel.bleConnectTransportName.value =
                            getString(R.string.transport_le)
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示设置BLE管理层的对话框
     */
    private fun showSetBleConnectPhyMaskDialog() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            toastL(R.string.ble_connect_phy_mask_not_support_with_low_system_version)
            return
        }
        AlertDialog.Builder(this)
            .setTitle(R.string.ble_connect_phy_mask_dialog_title)
            .setItems(R.array.ble_connect_phy_mask) { _, which ->
                when (which) {
                    //phy_le_1m_mask
                    0 -> {
                        singleConnectActivityViewModel.bleConnectPhyMask.value =
                            BleConnectPhyMask.PHY_LE_1M_MASK
                        singleConnectActivityViewModel.bleConnectPhyMaskName.value =
                            getString(R.string.connect_phy_le_1m_mask)
                    }
                    //phy_le_2m_mask
                    1 -> {
                        singleConnectActivityViewModel.bleConnectPhyMask.value =
                            BleConnectPhyMask.PHY_LE_2M_MASK
                        singleConnectActivityViewModel.bleConnectPhyMaskName.value =
                            getString(R.string.connect_phy_le_2m_mask)
                    }
                    //phy_le_coded_mask
                    2 -> {
                        singleConnectActivityViewModel.bleConnectPhyMask.value =
                            BleConnectPhyMask.PHY_LE_CODED_MASK
                        singleConnectActivityViewModel.bleConnectPhyMaskName.value =
                            getString(R.string.connect_phy_le_coded_mask)
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示设置超时时间的对话框
     */
    private fun showSetConnectTimeoutDialog() {
        val view = View.inflate(this, R.layout.view_ble_connect_timeout, null)
        val editText = view.findViewById<EditText>(R.id.connect_timeout_et)
        AlertDialog.Builder(this)
            .setTitle(R.string.set_ble_connect_timeout_dialog_title)
            .setView(view)
            .setPositiveButton(R.string.confirm) { _, _ ->
                var text = editText.text.toString()
                if (text.isEmpty()) {
                    text = "0"
                }
                BleManager.getConnectorInstance()
                    .setConnectTimeOut(text.toLong(), TimeUnit.MILLISECONDS)
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示更多选项的对话框
     */
    private fun showAdditionalOptionsDialog() {
        if (!connected) {
            toastL(R.string.additional_options_need_connect_after)
            return
        }
        AlertDialog.Builder(this)
            .setTitle(R.string.additional_options_dialog_title)
            .setItems(R.array.connect_additional_options) { _, which ->
                when (which) {
                    //开启可靠数据写入事务
                    0 -> {
                        beginReliableWrite()
                    }
                    //取消可靠数据写入模式
                    1 -> {
                        abortReliableWrite()
                    }
                    //读取RSSI
                    2 -> {
                        readRssi()
                    }
                    //更改MTU(单包数据最大值)
                    3 -> {
                        showSetMtuDialog()
                    }
                    //读取当前连接的物理层
                    4 -> {
                        readPhy()
                    }
                    //更改连接物理层
                    5 -> {
                        showChangePhyDialog()
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 开启可靠数据写入事务
     */
    private fun beginReliableWrite() {
        val device = scanResult?.device ?: return
        if (reliableWriteBegin) {
            toastL(R.string.already_in_reliable_write_mode)
            return
        }
        reliableWriteBegin = BleManager.getConnectorInstance().beginReliableWrite(device)
        if (!reliableWriteBegin) {
            toastL(R.string.reliable_write_mode_begin_failed)
        }
    }

    /**
     * 绑定（配对）设备
     */
    private fun bindDevice() {
        val boundState = BleManager.bindDevice(scanResult?.device ?: return)
        /*
         * 绑定设备，除非必要，否则请直接调用连接的方法
         * 注意：如果该设备不支持绑定，会直接回调绑定成功的回调，在绑定成功的回调中发起连接即可
         * 第一次绑定某一个设备会触发回调，之后再次绑定，可根据绑定时的函数的返回值来判断绑定状态，以进行下一步操作
         */
        when (boundState) {
            DeviceBoundErrorCode.DEVICE_BOND_REQUEST_FAILED -> DebugUtil.warnOut(
                TAG,
                "发起绑定失败(Failed to initiate binding)"
            )

            DeviceBoundErrorCode.DEVICE_BOND_BONDED -> {
                DebugUtil.warnOut(TAG, "此设备已经被绑定了(This device is already bound)")
                connectDevice()
            }

            DeviceBoundErrorCode.DEVICE_BOND_BONDING -> DebugUtil.warnOut(
                TAG,
                "此设备正在绑定中(This device is binding)"
            )

            DeviceBoundErrorCode.BLUETOOTH_ADAPTER_NULL -> DebugUtil.warnOut(
                TAG,
                "没有蓝牙适配器存在(No Bluetooth adapter exists)"
            )

            DeviceBoundErrorCode.BLUETOOTH_ADDRESS_INCORRECT -> DebugUtil.warnOut(
                TAG,
                "蓝牙地址错误(Bluetooth address is wrong)"
            )

            DeviceBoundErrorCode.DEVICE_BOND_REQUEST_SUCCESS -> {
                DebugUtil.warnOut(
                    TAG,
                    "向系统发起设备绑定请求成功(Successfully initiated device binding request to the system)"
                )
            }

            else -> DebugUtil.warnOut(TAG, "default")
        }
    }

    /**
     * 读取设备RSSI
     */
    private fun readRssi() {
        val device = scanResult?.device ?: return
        val succeed = BleManager.getConnectorInstance().readRemoteRssi(device)
        if (!succeed) {
            toastL(R.string.read_rssi_failed)
        }
    }

    /**
     * 显示设置MTU的对话框
     */
    private fun showSetMtuDialog() {
        val device = scanResult?.device ?: return
        val view = View.inflate(this, R.layout.view_set_mtu, null)
        val editText = view.findViewById<EditText>(R.id.mtu_et)
        AlertDialog.Builder(this)
            .setTitle(R.string.set_mtu)
            .setView(view)
            .setPositiveButton(R.string.confirm) { _, _ ->
                val text = editText.text.toString().trim()
                if (text.isEmpty()) {
                    return@setPositiveButton
                }
                val succeed = BleManager.getConnectorInstance().requestMtu(device, text.toInt())
                if (!succeed) {
                    toastL(R.string.request_mtu_failed)
                }
            }
            .setNeutralButton(R.string.cancel, null)
            .show()
    }

    /**
     * 读取当前连接的物理层
     */
    private fun readPhy() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            toastL(R.string.read_phy_not_support_with_low_system_version)
            return
        }
        val device = scanResult?.device ?: return
        val succeed = BleManager.getConnectorInstance().readPhy(device)
        if (!succeed) {
            toastL(R.string.read_phy_failed)
        }
    }

    /**
     * 显示读取物理层信息的结果的对话框
     */
    private fun showPhyReadResultDialog(txPhy: BlePhy, rxPhy: BlePhy) {
        AlertDialog.Builder(this)
            .setTitle(R.string.read_phy_result_dialog_title)
            .setMessage(getString(R.string.phy_read_result, txPhy.name, rxPhy.name))
            .setPositiveButton(R.string.confirm, null)
            .show()
    }

    /**
     * 显示物理层信息变更的对话框
     */
    private fun showPhyUpdateDialog(txPhy: BlePhy, rxPhy: BlePhy) {
        AlertDialog.Builder(this)
            .setTitle(R.string.phy_update_dialog_title)
            .setMessage(getString(R.string.phy_read_result, txPhy.name, rxPhy.name))
            .setPositiveButton(R.string.confirm, null)
            .show()
    }

    /**
     * 显示更连接改物理层的对话框
     */
    private fun showChangePhyDialog() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            toastL(R.string.change_phy_not_support_with_low_system_version)
            return
        }
        ChangeConnectedPhyDialog(
            this,
            object : ChangeConnectedPhyDialog.OnConfirmButtonClickListener {
                /**
                 * 确认按钮被点击的回调
                 */
                /**
                 * 确认按钮被点击的回调
                 */
                override fun onConfirmButtonClick(
                    txPhy: BlePhy,
                    rxPhy: BlePhy,
                    blePhyOptions: BlePhyOptions
                ) {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
                        toastL(R.string.change_phy_not_support_with_low_system_version)
                        return
                    }
                    val device = scanResult?.device ?: return
                    val succeed =
                        BleManager.getConnectorInstance()
                            .setPreferredPhy(device, txPhy, rxPhy, blePhyOptions)
                    if (!succeed) {
                        toastL(R.string.change_phy_failed)
                    }
                }
            })
            .show()
    }
}